/* 
 * File:   storage.cpp
 * Author: alexey
 * 
 * Created on 20 Март 2011 г., 1:27
 */

#include <string.h>
#include <map>
#include <stdexcept>
#include <stdio.h>
#include <iostream>

#include "storage.h"

using namespace storagemon;
FileObject::FileObject(const char* path,
                const char* name,
                char md5[MD5_DIGEST_SIZE],
                u_long id,
                u_long parent_id) :
                path_(path),
                name_(name),
                id_(id),
                parent_id_(parent_id)
{
    if (md5)
        memcpy(md5_, md5, MD5_DIGEST_SIZE);
    full_path_.append(path_.c_str()).append("/").append(name_.c_str());
}

FileObject::~FileObject()
{
}


u_long FileObject::id() const
{
    return id_;
}

const char* FileObject::name() const
{
    return name_.c_str();
}

const char* FileObject::path() const
{
    return path_.c_str();
}

const char* FileObject::full_path() const
{
    return full_path_.c_str();
}

u_long FileObject::parent_id() const
{
    return parent_id_;
}

char* FileObject::md5()
{
    return md5_;
}

char* FileObject::md5_string(char* md5)
{
    utils::md5_to_string(md5_, md5);
    return md5;
}

IService* storagemon::CreateStorageServiceFile(const char* name,
            const char* path, u_long id, u_long parent_id,
            char md5[MD5_DIGEST_SIZE])
{
    return new FileObject(name, path, md5, id, parent_id);
}


DirectoryObject::DirectoryObject(const char* name,
                const char* path,
                u_long id,
                u_long parent_id)
: id_(id), parent_id_(parent_id),
        name_(name), path_(path)

{
}

DirectoryObject::~DirectoryObject()
{

}

u_long DirectoryObject::id() const
{
    return id_;
}

u_long DirectoryObject::parent_id() const
{
    return parent_id_;
}

const char* DirectoryObject::name() const
{
    return name_.c_str();
}

const char* DirectoryObject::path() const
{
    return path_.c_str();
}

bool DirectoryObject::add_file(IFile* file)
{
    std::vector<IFile*>::iterator it;
    for (it = file_list_.begin(); it != file_list_.end(); ++it)
    {
        if (*(*it) == *file)
            break;
    }
    if (it == file_list_.end())
    {
        file_list_.push_back(file);
        return true;
    }
    return false;
}

bool DirectoryObject::remove_file(u_long id)
{
    std::vector<IFile*>::iterator it;
    for (it = file_list_.begin(); it != file_list_.end(); ++it)
    {
        if ((*it)->id() == id)
        {
            file_list_.erase(it);
            return true;
        }
    }
    return false;
}

u_long DirectoryObject::size() const
{
    return file_list_.size();
}

std::vector<IFile*>::iterator DirectoryObject::get_file(u_long id)
{
    if (id > file_list_.size())
        return file_list_.end();
    return file_list_.begin() + id;
}

IService* storagemon::CreateStorageServiceDirectory(const char* name,
            const char* path, u_long id, u_long parent_id,
            char md5[MD5_DIGEST_SIZE])
{
    return new DirectoryObject(name, path, id, parent_id);
}


StorageObject::StorageObject(const char* name,
                const char* path,
                u_long id)
: id_(id), name_(name), path_(path)
{
}

StorageObject::~StorageObject()
{

}

u_long StorageObject::id() const
{
    return id_;
}

const char* StorageObject::name() const
{
    return name_.c_str();
}

const char* StorageObject::path() const
{
    return path_.c_str();
}

bool StorageObject::add_dir(IDirectory* dir)
{
    std::vector<IDirectory*>::iterator it;
    for (it = dir_list_.begin(); it != dir_list_.end(); ++it)
    {
        if (*(*it) == *dir)
            break;
    }
    if (it == dir_list_.end())
    {
        dir_list_.push_back(dir);
        return true;
    }
    return false;
}

bool StorageObject::remove_dir(u_long id)
{
    std::vector<IDirectory*>::iterator it;
    for (it = dir_list_.begin(); it != dir_list_.end(); ++it)
    {
        if ((*it)->id() == id)
        {
            dir_list_.erase(it);
            return true;
        }
    }
    return false;
}

u_long StorageObject::size() const
{
    return dir_list_.size();
}

std::vector<IDirectory*>::iterator StorageObject::get_dir(u_long id)
{
    if (id > dir_list_.size())
        return dir_list_.end();
    return dir_list_.begin() + id;
}

IService* storagemon::CreateStorageServiceStorage(const char* name,
            const char* path, u_long id, u_long parent_id,
            char md5[MD5_DIGEST_SIZE])
{
    return new StorageObject(name, path, id);
}

StorageServiceFactory::StorageServiceFactory()
{

}

StorageServiceFactory::~StorageServiceFactory()
{

}

bool StorageServiceFactory::RegisterObject(const char* name,
        CreateStorageServiceCallback fn)
{
    return m_callbacks.insert(CallbackMap::value_type(name, fn)).second;
}

bool StorageServiceFactory::UnregisterObject(const char* name)
{
    return m_callbacks.erase(name) == 1;
}

IService* StorageServiceFactory::CreateService(const char* name,
        const char* p_name, const char* p_path, u_long p_id, u_long p_parent_id,
        char p_md5[MD5_DIGEST_SIZE])
{
    CallbackMap::const_iterator it = m_callbacks.find(name);
    if (it == m_callbacks.end())
        throw std::runtime_error("StorageServiceFactory::CreateService. Unknown identifier");
    return (it->second)(p_name, p_path, p_id, p_parent_id, p_md5);
}